package com.zengqingfa.designpattern.structure.proxy.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 *
 * @fileName: RealProxy
 * @author: zengqf3
 * @date: 2021-4-22 8:49
 * @description:
 */
public class ProxyFactory {

    private Object target;

    public ProxyFactory() {
    }

    public ProxyFactory(Object target) {
        this.target = target;
    }

    /**
     * 动态生成代理对象
     * @return
     */
    public <T> T getProxyInstance() {
        /**
         *      * @param   loader the class loader to define the proxy class
         *      * @param   interfaces the list of interfaces for the proxy class to implement
         *      * @param   h the invocation handler to dispatch method invocations to
         */
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("start.....");
                        // 执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("end.....");
                        return returnValue;
                    }
                });
    }

    /**
     * 动态生成代理对象
     * @return
     */
    public <T> T getProxyInstance2() {
        /**
         *      * @param   loader the class loader to define the proxy class
         *      * @param   interfaces the list of interfaces for the proxy class to implement
         *      * @param   h the invocation handler to dispatch method invocations to
         */
        return (T) Proxy.newProxyInstance(UserMapper.class.getClassLoader(), new Class[]{UserMapper.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //解析得到sql
                        // Select annotation = method.getAnnotation(Select.class);
                        // String sql = annotation.value()[0];
                        //
                        // //执行sql(模拟JDBC)
                        // System.out.println(sql + " executing...");
                        return null;
                    }
                });
    }

    public Object getMapper(Class clazz) {
        //调用newProxyInstance需要传入class数组
        Class[] mapperInterface = new Class[]{clazz};
        //把动态代理过程中生成的代理类保留下来，有助于新手理解动态代理（此行可省略）
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        System.out.println(System.getProperty("user.dir"));
        System.out.println(System.getProperty("user.home"));
        //通过动态代理生成Mapper
        Object object = Proxy
                .newProxyInstance(clazz.getClassLoader(), mapperInterface, new MyInvocationHandler());
        return object;
    }

    public static void main(String[] args) {
        ProxyFactory factory = new ProxyFactory();
        // Object proxyInstance2 = factory.getProxyInstance2();
        //class com.sun.proxy.$Proxy0
        // System.out.println(proxyInstance2.getClass());
        // System.out.println(proxyInstance2);

        UserMapper mapper = (com.zengqingfa.designpattern.structure.proxy.dynamic.UserMapper) factory.getMapper(UserMapper.class);
        //class com.sun.proxy.$Proxy0
        List<Object> list = mapper.queryAll();
        System.out.println(mapper.getClass());
        System.out.println(mapper);
    }
}
